#include "widget_node_material.h"
#include "ui_widget_node_material.h"
#include "../AvatarLibrary.h"
#include "input/input_color.h"

WidgetNodeMaterial::WidgetNodeMaterial(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::WidgetNodeMaterial)
{
    ui->setupUi(this);
    pbrEnable(false);
    ui->checkBoxCullFace->setCheckState(Qt::Checked);
    ui->checkBoxUseDepth->setCheckState(Qt::Checked);
    connect(ui->sliderRoughness, &QSlider::actionTriggered, this, &WidgetNodeMaterial::slider_actionTriggered);
    connect(ui->sliderMetalness, &QSlider::actionTriggered, this, &WidgetNodeMaterial::slider_actionTriggered);
    connect(ui->sliderEmissive, &QSlider::actionTriggered, this, &WidgetNodeMaterial::slider_actionTriggered);
    connect(ui->lineEditRoughness, &QLineEdit::editingFinished, this, &WidgetNodeMaterial::lineEdit_editingFinished);
    connect(ui->lineEditMetalness, &QLineEdit::editingFinished, this, &WidgetNodeMaterial::lineEdit_editingFinished);
    connect(ui->lineEditEmissive, &QLineEdit::editingFinished, this, &WidgetNodeMaterial::lineEdit_editingFinished);
    connect(ui->lineEditColor, &InputColor::textChanged, this, &WidgetNodeMaterial::lineEditColor_textChanged);
    connect(ui->checkBoxCullFace, &QCheckBox::checkStateChanged, this, &WidgetNodeMaterial::renderMode_checkStateChanged);
    connect(ui->checkBoxUseDepth, &QCheckBox::checkStateChanged, this, &WidgetNodeMaterial::renderMode_checkStateChanged);
    connect(ui->checkBoxAddColor, &QCheckBox::checkStateChanged, this, &WidgetNodeMaterial::renderMode_checkStateChanged);
    connect(ui->checkBoxWireframe, &QCheckBox::checkStateChanged, this, &WidgetNodeMaterial::renderMode_checkStateChanged);
    QDoubleValidator* val = new QDoubleValidator(this);
    val->setDecimals(2);
    val->setNotation(QDoubleValidator::StandardNotation);
    ui->lineEditRoughness->setValidator(val);
    ui->lineEditMetalness->setValidator(val);
    ui->lineEditEmissive->setValidator(val);
}

WidgetNodeMaterial::~WidgetNodeMaterial()
{
    delete ui;
}

void WidgetNodeMaterial::setupNode(const QString &name)
{
    _currentNode = Program::SceneNodeList[name];
    ui->checkBoxEnable->setCheckState(_currentNode->Material.Enable ? Qt::Checked : Qt::Unchecked);
    ui->lineEditRoughness->setText(QString::number(_currentNode->Material.Roughness));
    ui->lineEditMetalness->setText(QString::number(_currentNode->Material.Metalness));
    ui->lineEditColor->setValue(_currentNode->Material.Color);
    ui->lineEditEmissive->setText(QString::number(_currentNode->Material.Emissive));
    ui->sliderRoughness->setSliderPosition(_currentNode->Material.Roughness * 100);
    ui->sliderMetalness->setSliderPosition(_currentNode->Material.Metalness * 100);
    ui->sliderEmissive->setSliderPosition(_currentNode->Material.Emissive * 10);
    ui->checkBoxCullFace->setCheckState(_currentNode->Material.IsCullFace ? Qt::Checked : Qt::Unchecked);
    ui->checkBoxUseDepth->setCheckState(_currentNode->Material.IsUseDepth ? Qt::Checked : Qt::Unchecked);
    ui->checkBoxAddColor->setCheckState(_currentNode->Material.IsAddColor ? Qt::Checked : Qt::Unchecked);
    ui->checkBoxWireframe->setCheckState(_currentNode->Material.IsWireframe ? Qt::Checked : Qt::Unchecked);
}

void WidgetNodeMaterial::on_checkBoxEnable_checkStateChanged(const Qt::CheckState &state)
{
    _currentNode->Material.Enable = state == Qt::Checked;
    pbrEnable(_currentNode->Material.Enable);
    AvatarLibrary::avatar_command(_currentNode->ScriptMaterial());
}

void WidgetNodeMaterial::slider_actionTriggered(int action)
{
    QSlider* slider = qobject_cast<QSlider*>(sender());
    float value = slider->sliderPosition() * 0.01f;
    if (slider == ui->sliderRoughness)
    {
        _currentNode->Material.Roughness = value;
        ui->lineEditRoughness->setText(QString::number(value));
    }
    else if (slider == ui->sliderMetalness)
    {
        _currentNode->Material.Metalness = value;
        ui->lineEditMetalness->setText(QString::number(value));
    }
    else if (slider == ui->sliderEmissive)
    {
        _currentNode->Material.Emissive = value * 10.0f;
        ui->lineEditEmissive->setText(QString::number(value * 10.0f));
    }
    AvatarLibrary::avatar_command(_currentNode->ScriptMaterial());
}

void WidgetNodeMaterial::lineEdit_editingFinished()
{
    bool success;
    QLineEdit* lineEdit = qobject_cast<QLineEdit*>(sender());
    float value = lineEdit->text().toFloat(&success);
    if (success)
    {
        if (lineEdit == ui->lineEditRoughness)
        {
            _currentNode->Material.Roughness = value;
            ui->sliderRoughness->setSliderPosition(value * 100);
        }
        else if (lineEdit == ui->lineEditMetalness)
        {
            _currentNode->Material.Metalness = value;
            ui->sliderMetalness->setSliderPosition(value * 100);
        }
        else if (lineEdit == ui->lineEditEmissive)
        {
            _currentNode->Material.Emissive = value;
            ui->sliderEmissive->setSliderPosition(value * 10);
        }
        AvatarLibrary::avatar_command(_currentNode->ScriptMaterial());
    }
}

void WidgetNodeMaterial::lineEditColor_textChanged(const QString &text)
{
    _currentNode->Material.Color = text;
    AvatarLibrary::avatar_command(_currentNode->ScriptMaterial());
}

void WidgetNodeMaterial::renderMode_checkStateChanged(const Qt::CheckState &state)
{
    bool checked = state == Qt::Checked;
    QCheckBox* checkBox = qobject_cast<QCheckBox*>(sender());
    if (checkBox == ui->checkBoxCullFace) _currentNode->Material.IsCullFace = checked;
    else if (checkBox == ui->checkBoxUseDepth) _currentNode->Material.IsUseDepth = checked;
    else if (checkBox == ui->checkBoxAddColor) _currentNode->Material.IsAddColor = checked;
    else if (checkBox == ui->checkBoxWireframe) _currentNode->Material.IsWireframe = checked;
    QString faceMode = _currentNode->Material.IsCullFace ? "scene.FACE_FRONT" : "scene.FACE_DOUBLE";
    QString blendMode = _currentNode->Material.IsAddColor ? "scene.BLEND_ADDITIVE" : "scene.BLEND_NORMAL";
    QString useDepth = _currentNode->Material.IsUseDepth ? "true" : "false";
    QString wirefame = _currentNode->Material.IsWireframe ? "true" : "false";
    AvatarLibrary::avatar_command(QString("scene.renderMode('%1',%2,%3,%4,%5)").arg(_currentNode->Name, faceMode, blendMode, useDepth, wirefame));
}

void WidgetNodeMaterial::pbrEnable(bool enable)
{
    ui->lineEditRoughness->setEnabled(enable);
    ui->lineEditMetalness->setEnabled(enable);
    ui->lineEditColor->setEnabled(enable);
    ui->lineEditEmissive->setEnabled(enable);
    ui->sliderRoughness->setEnabled(enable);
    ui->sliderMetalness->setEnabled(enable);
    ui->sliderEmissive->setEnabled(enable);
}
